package cc.owoo.godpen.structure;

import java.util.AbstractCollection;
import java.util.Iterator;

/**
 * Created by nimensei
 * 2022-03-07 上午 01:58
 **/
public class TaskList<T> implements Iterable<TaskList.Node<T>> {
    private final ValuesIterable<T> valuesIterable = new ValuesIterable<>(this);// 值迭代器
    private Node<T> first;// 头节点
    private Node<T> last;// 尾节点
    private int size;// 长度

    public TaskList() {
    }

    public TaskList(TaskList<? extends T> list) {
        pushList(list);
    }

    public TaskList(Iterable<? extends T> values) {
        pushList(values);
    }

    /**
     * 向数组的末尾添加一个元素，并返回新的长度
     *
     * @param values 元素
     * @return 新的长度
     */
    public int push(T... values) {
        if (values == null)
            return size;
        for (T value : values)
            pushValue(value);
        return size;
    }

    /**
     * 向数组的末尾添加一个或多个元素，并返回新的长度
     *
     * @param list 元素
     * @return 新的长度
     */
    public int push(TaskList<? extends T> list) {
        return pushList(list);
    }


    /**
     * 向数组的末尾添加一个或多个元素，并返回新的长度
     *
     * @param values 元素
     * @return 新的长度
     */
    public int push(AbstractCollection<? extends T> values) {
        return pushList(values);
    }

    /**
     * 向数组的末尾添加一个或多个元素，并返回新的长度
     *
     * @param list 元素
     * @return 新的长度
     */
    public int pushList(TaskList<? extends T> list) {
        if (list == null)
            return size;
        Node<? extends T> now = list.first;
        while (now != null) {
            pushValue(now.value);
            now = now.next;
        }
        return size;
    }

    /**
     * 向数组的末尾添加一个或多个元素，并返回新的长度
     *
     * @param values 元素
     * @return 新的长度
     */
    public int pushList(Iterable<? extends T> values) {
        if (values == null)
            return size;
        values.forEach(this::pushValue);
        return size;
    }

    /**
     * 向数组的末尾添加一个元素
     *
     * @param value 值
     */
    public void pushValue(T value) {
        Node<T> node = new Node<>(this, value);
        if (first == null)
            first = last = node;
        else {
            node.prev = last;
            last = last.next = node;
        }
        ++size;
    }

    /**
     * 向数组的头部添加一个或多个元素，返回新的长度
     *
     * @param values 元素
     * @return 新的长度
     */
    public int unshift(T... values) {
        if (values == null)
            return size;
        for (T value : values)
            unshiftValue(value);
        return size;
    }

    /**
     * 向数组的头部添加一个或多个元素，返回新的长度
     *
     * @param values 元素
     * @return 新的长度
     */
    public int unshift(Iterable<T> values) {
        if (values == null)
            return size;
        values.forEach(this::unshiftValue);
        return size;
    }

    /**
     * 向数组的头部添加一个元素
     *
     * @param value 值
     */
    private void unshiftValue(T value) {
        Node<T> node = new Node<>(this, value);
        if (first == null)
            first = last = node;
        else {
            node.next = first;
            first = last.prev = node;
        }
        ++size;
    }

    /**
     * 删除数组的最后一个元素，数组的长度减1，并且返回删除元素的值(数组为空时，不改变数组，并返回null)
     *
     * @return 删除的元素
     */
    public T pop() {
        if (last == null)
            return null;
        T value = last.value;
        remove(last);
        --size;
        return value;
    }

    /**
     * 删除并返回数组的第一个元素，数组的长度减1，并且返回删除元素的值(数组为空时，不改变数组，并返回null)
     *
     * @return 删除的元素
     */
    public T shift() {
        if (first == null)
            return null;
        T value = first.value;
        if (first == last)
            first = last = null;
        else {
            first = first.next;
            first.prev = null;
        }
        --size;
        return value;
    }

    /**
     * 颠倒数组中的元素顺序
     *
     * @return 新的链表对象
     */
    public TaskList<T> reverse() {
        TaskList<T> list = new TaskList<>();
        Node<T> now = first;
        while (now != null) {
            Node<T> node = new Node<>(list, now.value);
            if (list.first == null)
                list.first = list.last = node;
            else {
                node.next = list.first;
                list.first = list.first.prev = node;
            }
            now = now.next;
        }
        list.size = size;
        return list;
    }

    public T get(int i) {
        if (i < 0 || i >= size)
            return null;
        Node<T> now = first;
        int index = 0;
        while (now != null) {
            if (index == i)
                return now.value;
            now = now.next;
            ++index;
        }
        return null;
    }

    /**
     * 删除该值的结点
     *
     * @param value 值
     */
    public void remove(T value) {
        Node<T> now = first;
        while (now != null) {
            if (now.value == value)
                remove(now);
            now = now.next;
        }
    }

    /**
     * 删除节点
     *
     * @param node 节点
     */
    public void remove(Node<T> node) {
        if (node.list != this)
            throw new IllegalArgumentException("节点不属于该链表下");
        if (node == first) {
            if (size == 1)
                first = last = null;
            else {
                first = first.next;
                first.prev = null;
            }
        } else if (node == last) {
            if (size == 1)
                first = last = null;
            else {
                last = last.prev;
                last.next = null;
            }
        } else {
            node.prev.next = node.next;
            node.next.prev = node.prev;
        }
        --size;
    }

    public int size() {
        return size;
    }

    public void clear() {
        Node<T> now = first;
        while (now != null) {
            if (now.prev != null) {
                now.prev.next = null;
                now.prev = null;
            }
            now = now.next;
        }
        first = last = null;
        size = 0;
    }

    @Override
    public Iterator<Node<T>> iterator() {
        return new Iterator<>() {
            Node<T> now = first;

            @Override
            public boolean hasNext() {
                return now != null;
            }

            @Override
            public Node<T> next() {
                Node<T> value = now;
                now = now.next;
                return value;
            }
        };
    }

    /**
     * 获取元素迭代器
     *
     * @return 迭代器
     */
    public Iterable<T> values() {
        return valuesIterable;
    }

    @Override
    public String toString() {
        StringBuilder string = new StringBuilder();
        string.append('[');
        Node<T> now = first;
        while (now != null) {
            if (string.length() > 1)
                string.append(", ");
            string.append(now.value);
            now = now.next;
        }
        string.append(']');
        return string.toString();
    }

    /**
     * 值迭代器
     *
     * @param <T> 值类型
     */
    private static class ValuesIterable<T> implements Iterable<T> {
        private TaskList<T> list;

        public ValuesIterable(TaskList<T> list) {
            this.list = list;
        }

        @Override
        public Iterator<T> iterator() {
            return new Iterator<T>() {
                Node<T> now = list.first;

                @Override
                public boolean hasNext() {
                    return now != null;
                }

                @Override
                public T next() {
                    T value = now.value;
                    now = now.next;
                    return value;
                }
            };
        }
    }

    /**
     * 节点
     *
     * @param <T> 值
     */
    public static class Node<T> {
        private TaskList<T> list;// 所在链表
        private Node<T> prev;// 上一个节点
        private Node<T> next;// 下一个节点
        public T value;

        public Node(TaskList<T> list, T value) {
            this.list = list;
            this.value = value;
        }

        /**
         * 删除当前接待你
         */
        public void remove() {
            list.remove(this);
        }
    }
}
